13
Metodología de Diseño de Foster
De "Designing and Building Parallel Programs" por Ian Foster
Cuatro pasos:
Particionar
Dividir cómputo y datos
Comunicación
Intercambio de datos entre cómputos
Aglomeración
Agrupar tareas para mejorar rendimiento
Mapeo
Asignar tareas a procesadores/hilos
14
Diseñando programas paralelos
Particionar
Divide el problema en tareas
Comunicar
Determina la cantidad y el patrón de comunicación
Aglomerar
Combinar tareas
Mapear
Asignar tareas aglomeradas a los hilos generados
(Gp:) Problema
(Gp:) Tareas iniciales
(Gp:) Comunicación
(Gp:) Tareas combinadas
Programa final
15
Modelos de Programación Paralela
Descomposición funcional
Paralelismo de tareas
Dividir el cómputo, asociarle datos
Tareas independientes del mismo problema
Descomposición de datos
La misma operación ejecutando diferentes datos
Dividir datos en piezas, asociarles cómputo
16
Métodos de descomposición
Descomposición funcional
Enfocarse a cómputo puede revelar la estructura en un problema
(Gp:) Grid reprinted with permission of Dr. Phu V. Luong, Coastal and Hydraulics Laboratory, ERDC
Descomposición por dominio
Enfocarse en la estructura de datos más grande o más frecuentemente accesada
Paralelismo en los datos
La misma operación aplicada a todos los datos
(Gp:) Modelo atmosférico
(Gp:) Modelo Oceano
(Gp:) Modelo terrestre
(Gp:) Modelo de hidrología
17
Descomposición en Pipeline
La computación se hace en etapas independientes
Descomposición funcional
Los hilos se asignan a una etapa a computar
Línea de ensamble de automóviles
Descomposición de datos
Los hilos procesan todas las etapas de una sola instancia
Un trabajador construye un auto completito
18
Ejemplo de LAME Encoder
LAME MP3 encoder
Proyecto Open source
Herramienta educativa
El objetivo de este proyecto es
Mejorar la calidad
Mejorar la velocidad de la codificación a MP3
19
Estrategia de LAME Pipeline
(Gp:) Frame N
(Gp:) Frame N + 1
(Gp:) Tiempo
(Gp:) Otro N
(Gp:) Preludio N
(Gp:) Acústicos N
(Gp:) Codificación N
(Gp:) T 2
(Gp:) T 1
(Gp:) Acústicos N+1
(Gp:) Preludio N+1
(Gp:) Otro N+1
(Gp:) Codificación N+1
(Gp:) Acústicos N+2
(Gp:) Preludio N+2
(Gp:) T 3
(Gp:) T 4
(Gp:) Preludio N+3
(Gp:) Barrera Jerárquica
Otro
Preludio
Acústicos
Codificación
Frame
(Gp:) Extraer siguiente frame
Caracterización del frame
Poner parámetros del encoder
(Gp:) Analisis
FFT long/short
Ensamblar el filtro
(Gp:) Aplicar filtros
Suprimir ruidos
Cuantiza y cuenta bits
(Gp:) Agregar encabezado del frame
Verificar si es correcto
Escribe al disco
20
Diseño
¿Cuál es el beneficio esperado?
¿Cómo logramos esto con el menor esfuerzo?
¿Cuánto se lleva paralelizar?
¿Cuánto esfuerzo se requiere para rediseñar?
Prototipo rápido con OpenMP
Aceleración(2P) = 100/(96/2+4) = ~1.92X
21
OpenMP
Paralelismo Fork-join:
El hilo maestro se divide en un grupo de hilos como sea necesario
El paralelismo va incrementando
Un programa secuencial evoluciona a un programa paralelo
(Gp:) Regiones Paralelas
(Gp:) Hilo maestro
22
Diseño
#pragma omp parallel for
for( int i = start; i < = end; i+= 2 ){
if( TestForPrime(i) )
globalPrimes[gPrimesFound++] = i;
ShowProgress(i, range);
}
(Gp:) OpenMP
(Gp:) Crea hilos aquí para
Esta región paralela
(Gp:) Divide iteraciones de el ciclo for
23
Actividad 3
Ejecuta la versión OpenMP del código
Localiza el directorio PrimeOpenMP y la solución
Compila el código
Ejecuta con '1 5000000' para comparar
¿Cuál es la aceleración?
24
Diseño
¿Cuál es el beneficio esperado?
¿Cómo logras esto con el menor esfuerzo?
¿Cuánto tiempo se llevó paralelizar?
¿Cuánto esfuerzo se requiere para rediseñar?
¿Es la mejor aceleración posible?
Aceleración de 1.40X (menor que 1.92X)
25
Depuración
¿Es la implementación correcta de paralelismo?
No! Los resultados son diferentes cada ejecución .
26
Depuración
Intel® Parallel Inspector indica errores notorios en la paralelizacion como condiciones de concurso e interbloqueos
Análisis de errores en la paralelización
Intel® Parallel Inspector
Dónde están los Interbloqueos o Condiciones de Concurso
Colector
De Datos
en tiempo de ejecución
27
Intel® Parallel Inspector (Errores en la Paralelización)
Seleccionar información en relación con condiciones de concurso e interbloqueos
Ver la descripción general de errores de la paralelización (Ti3)
Selecciona el error e inspecciona el código
28
Actividad 4
Usa Parallel Inspector para analizar la aplicación paralelizada
Usa Intel Parallel Inspector para encontrar la condición de concurso que hace que el cálculo de números primos sea incorrecto
Ejecuta la aplicación
¿Se reportan errores?
29
Depuración
¿Cuánto esfuerzo de requiere para rediseñar?
¿Cuánto nos llevará paralelizar?
Parallel Inspector solo reportó 3 dependencias, por lo tanto no hay mayores compliaciones
30
Depuración
#pragma omp parallel for
for( int i = start; i < = end; i+= 2 ){
if( TestForPrime(i) )
#pragma omp critical
globalPrimes[gPrimesFound++] = i;
ShowProgress(i, range);
}
#pragma omp critical
{
gProgress++;
percentDone = (int)(gProgress/range *200.0f+0.5f)
}
(Gp:) Creará una sección crítica para esta referencia
(Gp:) Creará una sección crítica para ambas referencias
31
Actividad 5
Modifica y ejecuta la versión de Open MP del código
Añade pragmas de regiones críticas al código
Compila el código
Ejecuta Parallel Inspector (Errores de Paralelización)
Si los errores siguen presentes, haz las correcciones apropiadas al código y ejecuta de nuevo en Parallel Inspector
Ejecuta con '1 5000000' para comparar
Compila y ejecuta sin debugging
¿Cuál es la aceleración?
32
Depuración
Respuesta correcta, pero el rendimiento bajo al ~1.33X
¿Es lo mejor que podemos esperar de este algoritmo?
No! De acuerdo a la Ley de Amdahl, podemos esperar una aceleración cerca de 1.9X
33
Problemas comunes de rendimiento
Sobrecarga en paralelo
Dada por la creación de hilos, planificación.
Sincronización
Datos globales excesivos, contención de los mismos objetos de sincronización
Carga desbalanceada
Distribución no adecuada del trabajo en paralelo
Granularidad
No hay suficiente trabajo paralelo
34
Afinando para mejorar el rendimiento
Parallel Amplifier (Locks y Waits) apunta a cuellos de botella en el rendimiento en aplicaciones con hilos
(Gp:) Locks & Waits
(Gp:) Intel® Parallel Amplifier
35
Parallel Amplifier/ Locks y Waits
La gráfica muestra una porción de tiempo significativa en condición ociosa como resultado de la sección crítica
FindPrimes() y ShowProgress() están significativamente impactadas por el tiempo ocioso ocurriendo en la sección crítica
36
Parallel Amplifier/ Locks y Waits
ShowProgress() consume 558/657 (85%) del tiempo permaneciendo ocioso en una sección crítica
Haz Double Click en ShowProgress() en la sección crítica más larga para ver el código fuente
37
Parallel Amplifier/ Resumen
El tiempo transcurrido muestra .571 sec
Tiempo de espera/ Núcleos = 1.87/4 =.47 sec
Esperando el 82% del tiempo transcurrido en una sección crítica
La mayoría del tiempo 1 núcleo y ocasionalmente están ocupados 2
38
Parallel Amplifier/ Concurrencia
Concurrencia (Function -Caller Function Tree)
ShowProgress es llamada de FindPrimes y representa mayormente la razón por la cual la concurrencia es pobre
39
Parallel Amplifier/ Concurrencia
Concurrencia (Thread -Function -Caller Function Tree)
Esta pantalla muestra como cada hilo contribuye al problema de concurrencia
Expandiendo cualquier hilo las funciones que más contibuyen
40
Rendimiento
Double Click en ShowProgress en la segunda sección crítica más larga
Esta implementación tiene llamadas de sincronización implícita – printf
Esto limita la mejora del rendimiento debido a cambios de contexto resultantes
De regreso a la etapa de diseño
41
Actividad 6
Usar Parallel Amplifier para analizar la aplicación con hilos
Usar la herramienta Parallel Amplifier (Análisis de Locks y Waits)
Identifica los waits y locks que más contribuyen
42
Rendimiento
¿Es esto mucha contención esperada?
El algoritmo tiene muchas más actualizaciones a variables que las 10 necesitadas para mostrar el progreso
void ShowProgress( int val, int range )
{
int percentDone;
gProgress++;
percentDone = (int)((float)gProgress/(float)range*200.0f+0.5f);
if( percentDone % 10 == 0 )
printf("bbbb%3d%%", percentDone);
}
void ShowProgress( int val, int range )
{
int percentDone;
static int lastPercentDone = 0;
#pragma omp critical
{
gProgress++;
percentDone = (int)((float)gProgress/(float)range*200.0f+0.5f);
}
if( percentDone % 10 == 0 && lastPercentDone < percentDone / 10){
printf("bbbb%3d%%", percentDone);
lastPercentDone++;
}
}
Este cambio debe arreglar el problema de contención
43
Diseño
Meta
Elimina la contención debido a la sincronización implícita
¡La aceleración es 2.32X ! ¿Es correcto?
44
Rendimiento
Nuestra medida base original tenía la actualización del algoritmo de progreso "defectuoso"
¿Es lo mejor que podemos esperar de este algoritmo?
¡La aceleración actual es 1.40X (< < 1.9X)!
45
Actividad 7
Modifica la función ShowProgress (en la versiones serial y OpenMP) para solo mostrar la salida necesaria
Recompila y ejecuta el programa
Asegurarse que no se están usando banderas de instrumentación
¿Cuál es la aceleración con respecto a la versión serial?
if( percentDone % 10 == 0 && lastPercentDone < percentDone){
printf("bbbb%3d%%", percentDone);
lastPercentDone += 10;
}
46
Revisando el Rendimiento
Locks y Waits – Antes y Después de cambiar a la función printf
En la versión más rápida – el printf es llamado ~ 10x menos veces – lastPercentDone < percentDone / 10
Locks y Waits "self wait count" y "poor" muestran una diferencia significativa entre versiones
47
Revisando el Rendimiento
Veamos los Locks de OpenMP.
void FindPrimes(int start, int end)
{
// start is always odd
int range = end – start + 1;
#pragma omp parallel for
for( int i = start; i < = end; i += 2 )
{
if( TestForPrime(i) )
#pragma omp critical
globalPrimes[gPrimesFound++] = i;
ShowProgress(i, range);
}
}
(Gp:) Hay un lock en un ciclo
void FindPrimes(int start, int end)
{
// start is always odd
int range = end – start + 1;
#pragma omp parallel for
for( int i = start; i < = end; i += 2 )
{
if( TestForPrime(i) )
globalPrimes[InterlockedIncrement(&gPrimesFound)] = i;
ShowProgress(i, range);
}
}
48
Revisando el Rendimiento
Veamos el segundo lock
void ShowProgress( int val, int range )
{
int percentDone;
static int lastPercentDone = 0;
#pragma omp critical
{
gProgress++;
percentDone = (int)((float)gProgress/(float)range*200.0f+0.5f);
}
if( percentDone % 10 == 0 && lastPercentDone < percentDone / 10){
printf("bbbb%3d%%", percentDone);
lastPercentDone++;
}
}
(Gp:) Este es un lock que está siendo llamado dentro de un ciclo
void ShowProgress( int val, int range )
{
long percentDone, localProgress;
static int lastPercentDone = 0;
localProgress = InterlockedIncrement(&gProgress);
percentDone = (int)((float)localProgress/(float)range*200.0f+0.5f);
if( percentDone % 10 == 0 && lastPercentDone < percentDone / 10){
printf("bbbb%3d%%", percentDone);
lastPercentDone++;
}
}
49
Actividad 8
Modifica las regiones críticas de OpenMP para usar InterlockedIncrement en vez de
Re-compila y ejecuta el programa
´¿Cuál es la aceleración con respecto a la versión serial?
50
Análisis del balanceo de carga
Usa el análisis de concurrencia de Parallel Amplifier
Selecciona "Thread -Function -Caller Function Tree"
Observa que los 4 hilos hacen cantidades de trabajo desiguales
51
Arreglando el Desbalanceo de Carga
Distribuye el trabajo de manera más uniforme
(Gp:) void FindPrimes(int start, int end)
{
// start is always odd
int range = end – start + 1;
#pragma omp parallel for schedule(static,8)
for( int i = start; i < = end; i += 2 )
{
if( TestForPrime(i) )
globalPrimes[InterlockedIncrement(&gPrimesFound)] = i;
ShowProgress(i, range);
}
}
La aceleración lograda es 1.68X
52
Modifica el código para un mejor balanceo de carga
Añade la cláusula schedule (static, 8) al pragma de OpenMP parallel for
Re-compila y ejecuta el programa
¿Cuál es la aceleración comparada con la versión serial?
Actividad 9
53
Análisis final de balanceo de carga
La aceleración lograda es 1.80X
54
Análisis Comparativo
Paralelizar aplicaciones requiere varias iteraciones a través del ciclo de desarrollo de software
55
Metodología de paralelización Lo que se Cubrió
Cuatro pasos del ciclo de desarrollo para escribir aplicaciones paralelas desde el código serial y las herramientas de Intel® para soportar cada paso
Análisis
Diseño (Introducir Hilos)
Depurar para la correctud
Afinar el rendimiento
Las aplicaciones paralelas requieren múltiples iteraciones de diseño, depuración y afinación de rendimiento
Usar las herramientas para mejorar productividad
Página anterior | Volver al principio del trabajo | Página siguiente |